﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MindDrone.MindsetAPI;
using GalaSoft.MvvmLight.Command;
using System.Diagnostics;
using System.Windows.Threading;
using MindDrone.Helpers;
using ARDroneConnector;
using MindDrone.Common;
using GalaSoft.MvvmLight.Messaging;

namespace MindDrone.ViewModels
{
    public class HomeViewModel : ViewModelBase
    {
        #region mindset properties 
        private string _selectedPort;
        public string SelectedPort
        {
            get { return _selectedPort; }
            set
            {
                if (_selectedPort != value)
                {
                    _selectedPort = value;
                    OnPropertyChanged(SelectedPortPropertyName);
                }
            }
        }
        public const string SelectedPortPropertyName = "SelectedPort";

        private float _meditation;
        public float Meditation
        {
            get { return _meditation; }
            set
            {
                if (_meditation != value)
                {
                    _meditation = value;
                    OnPropertyChanged(MeditationPropertyName);
                }
            }
        }
        public const string MeditationPropertyName = "Meditation";

        private float minsetSignal;
        public float MindsetSignal
        {
            get { return minsetSignal; }
            set
            {
                if (minsetSignal != value)
                {
                    minsetSignal = value;
                    OnPropertyChanged(MindsetSignalPropertyName);
                }
            }
        }
        public const string MindsetSignalPropertyName = "MindsetSignal";


        private WrapperMindset ThinkGearWrapper { get; set; }
        public RelayCommand ConnectCommand { get; set; }
        public RelayCommand DisconnectCommand { get; set; }

        #endregion

        #region drone
        //public ArDroneConnector DroneWrapper { get; set ; }
        private ArDroneConnector _droneWrapper;
        public ArDroneConnector DroneWrapper
        {
            get { return _droneWrapper; }
            set
            {
                if (_droneWrapper != value)
                {
                    _droneWrapper = value;
                    OnPropertyChanged(DroneWrapperPropertyName);
                }
            }
        }
        public const string DroneWrapperPropertyName = "DroneWrapper";

        
        public RelayCommand DroneConnectCommand { get; set; }
        public RelayCommand DroneDisconnectCommand { get; set; }
        public RelayCommand DroneLandCommand { get; set; }
        public RelayCommand DroneTakeOffCommand { get; set; }
        public RelayCommand StartVideoCommand { get; set; }
        private string ssId;
        public string SsId
        {
            get { return ssId; }
            set
            {
                if (ssId != value)
                {
                    ssId = value;
                    OnPropertyChanged(SsIdPropertyName);
                }
            }
        }
        public const string SsIdPropertyName = "SsId";

        private ConnectorStatus _droneStatus;
        public ConnectorStatus DroneStatus
        {
            get { return _droneStatus; }
            set
            {
                if (_droneStatus != value)
                {
                    _droneStatus = value;
                    OnPropertyChanged(DroneStatusPropertyName);
                }
            }
        }
        public const string DroneStatusPropertyName = "DroneStatus";

        

        
        #endregion

        #region mindset logic
        private static int AVERAGE_COUNT = 5;
        private List<float> lstMeditationValues { get; set; }
        private float oldAverage { get; set; }
        #endregion

        #region Commands Validation Drone


        private bool CanExecuteDroneCommand()
        {
            if (DroneWrapper == null)
                return false;
            else
                return true;
        }
        private bool CanExecuteDisconnectCommand()
        {
            if (DroneWrapper != null && DroneWrapper.Status == ConnectorStatus.Open)
                return true;
            else
                return false;
        }
        private bool CanExecuteConnectCommand()
        {
            if (DroneWrapper == null)
                return true;
            if (DroneWrapper.Status == ConnectorStatus.Closed || DroneWrapper.Status == ConnectorStatus.CloseRequested)
                return true;

            return false;
        }
        #endregion

        public HomeViewModel()
        {    
            //mindset
            ThinkGearWrapper = new WrapperMindset();
            ThinkGearWrapper.OnMindsetChanged += new EventHandler<MindsetArgs>(ThinkGearWrapper_OnMindsetChanged);
            ConnectCommand = new RelayCommand(() =>
                {
                    ThinkGearWrapper.Connect(SelectedPort);
                });

            DisconnectCommand = new RelayCommand(() =>
                {
                    ThinkGearWrapper.Disconnect();   
                });

            //drone
            DroneStatus = ConnectorStatus.Closed;
            DroneConnectCommand = new RelayCommand(() =>
                {
                    if (DroneWrapper == null)
                    {
                        DroneWrapper = new ArDroneConnector(SsId);
                        DroneWrapper.OnStatusChanged += new EventHandler<DroneEventArgs>(DroneWrapper_OnStatusChanged);
                    }
                    
                    DroneWrapper.Connect();

                }, CanExecuteConnectCommand);
            DroneDisconnectCommand = new RelayCommand(() =>
                {
                    DroneWrapper.Disconnect();
                }, CanExecuteDisconnectCommand);

            DroneLandCommand = new RelayCommand(() =>
                {
                    if(DroneWrapper != null)
                        DroneWrapper.Land();
                }, CanExecuteDroneCommand);
            DroneTakeOffCommand = new RelayCommand(() =>
                {
                    if(DroneWrapper!= null)
                        DroneWrapper.TakeOff();
                }, CanExecuteDroneCommand);
            StartVideoCommand = new RelayCommand(() =>
                {
                    DroneWrapper.StartVideo();
                });
            if (Settings.IsTest)
            {
                DispatcherTimer timer = new DispatcherTimer();
                timer.Interval = TimeSpan.FromSeconds(2);
                timer.Tick += new EventHandler(timer_Tick);
                timer.Start();
            }
            SsId = "ardrone_087836";
        }

       

        void DroneWrapper_OnStatusChanged(object sender, DroneEventArgs e)
        {
            Tracer.Log(e.Status.ToString());
            DroneStatus = e.Status;
        } 
      
        void timer_Tick(object sender, EventArgs e)
        {
            Random rd = new Random(DateTime.Now.Millisecond);
            Meditation = rd.Next(100);
        }
        
        void ThinkGearWrapper_OnMindsetChanged(object sender, MindsetArgs e)
        {   
            Meditation = e.Attention;
            MindsetSignal = e.PoorSignal;

            lstMeditationValues.Add(Meditation);

            //TODO make this more accurate and better ?
            if (lstMeditationValues.Count >= AVERAGE_COUNT)
            {
                float move = 0f;
                float average = lstMeditationValues.Average();
                if (average < oldAverage)
                    move = -0.1f;
                else
                    move = 0.1f;

                //move drone
                if (DroneWrapper != null)
                    DroneWrapper.Move(0f, 0f, move, 0f);

                lstMeditationValues.Clear();
            }
            
        }
    }
}
